from vec3 import Vec3
from pointMass import PointMass
from spring import Spring

class SolidMass:
    def __init__(self):
        self.clear()

    def clear(self):
        self.pointMasses = []
        self.springs = []

    def getBoundingRadius(self):
        assert self.pointMasses
        center = self.getCenter()
        return max([(pm.pos - center).length() for pm in self.pointMasses])

    def getBoundingBox(self):
        minx = min([pm.pos.x for pm in self.pointMasses])
        maxx = max([pm.pos.x for pm in self.pointMasses])
        miny = min([pm.pos.y for pm in self.pointMasses])
        maxy = max([pm.pos.y for pm in self.pointMasses])
        minz = min([pm.pos.z for pm in self.pointMasses])
        maxz = max([pm.pos.z for pm in self.pointMasses])
        return Vec3(minx,miny,minz), Vec3(maxx,maxy,maxz)

    def getCenter(self):
        assert self.pointMasses
        return sum([pm.pos for pm in self.pointMasses],Vec3()) / float(len(self.pointMasses))
    
    def tick(self, dt):
        for spring in self.springs:
            if spring.broken:
                self.springs.remove(spring)
            else:
                spring.tick(dt)

        for pm in self.pointMasses:
            pm.tick(dt)

    def build(self, posMassList, indexLengthList, stiffness):
        self.clear()
        
        for pos, mass in posMassList:
            pointMass = PointMass(pos = pos, mass = mass)
            self.pointMasses.append(pointMass)

        for i1, i2, length in indexLengthList:
            spring = Spring(self.pointMasses[i1],
                            self.pointMasses[i2],
                            length = length,
                            stiffness = stiffness)
            self.springs.append(spring)
            
    def closestPointMassTo(self, pos):
        minPm = None
        minDist = None
        
        for pm in self.pointMasses:
            d = (pm.pos - pos).length()
            if not minPm or d < minDist:
                minPm = pm
                minDist = d
                
        return minPm
            
    def updateCollision(self):
        pass
            
    def testCollision(self, pm):
        return False

    def reactCollision(self, pm):
        pass
